import {Injectable} from '@nestjs/common';
// ORM
import {InjectRepository} from '@nestjs/typeorm';
import {Repository, UpdateResult} from 'typeorm';
import {RecordListEntity} from '../entity/record.list.entity';
import {RecordListDto} from '../dto/record.list.dto';
import {UserListEntity} from "../entity/user.list.entity";
import {calChatPriceByPrice} from "../common/common";
import Decimal from "decimal.js";

@Injectable()
export class RecordListService {
    constructor(
        @InjectRepository(RecordListEntity)
        private readonly recordRepository: Repository<RecordListEntity>,
    ) {
    }

    async createOne(recordListDto: RecordListDto): Promise<RecordListEntity> {
        return await this.recordRepository.save(recordListDto);
    }

    async getOneByUserIdDateAndModel(userId: string, date: string, model: string): Promise<RecordListEntity> {
        const qb = this.recordRepository.createQueryBuilder('record');
        qb.where({userId, date, model})
        return await qb.getOne()
    }

    async createUpdateOne(recordListDto: RecordListDto, modelPrice: {inPrice: number, outPrice: number}): Promise<void> {
        return await this.recordRepository.manager.transaction(async (entityManager) => {
            const record = await entityManager.findOne(RecordListEntity, {
                where: {
                    userId: recordListDto.userId,
                    date: recordListDto.date,
                    model: recordListDto.model
                }
            })
            if (record) {
                record.inToken = Number(record.inToken) + recordListDto.inToken
                record.outToken = Number(record.outToken) + recordListDto.outToken
                record.totalToken = Number(record.totalToken) + recordListDto.totalToken
                record.inPrice = new Decimal(record.inPrice).plus(new Decimal(modelPrice.inPrice).div(1000).times(recordListDto.inToken)).valueOf()
                record.outPrice = new Decimal(record.outPrice).plus(new Decimal(modelPrice.outPrice).div(1000).times(recordListDto.outToken)).valueOf()
                await entityManager.save(RecordListEntity, record)
            } else {
                recordListDto.inPrice = new Decimal(modelPrice.inPrice).div(1000).times(recordListDto.inToken).valueOf()
                recordListDto.outPrice = new Decimal(modelPrice.outPrice).div(1000).times(recordListDto.outToken).valueOf()
                await entityManager.save(RecordListEntity, recordListDto)
            }
            const user = await entityManager.findOne(UserListEntity, {
                where: {
                    userId: recordListDto.userId,
                }
            })
            user.balance = new Decimal(user.balance).minus(calChatPriceByPrice({
                inPrice: modelPrice.inPrice,
                outPrice: modelPrice.outPrice
            }, {
                inTokens: recordListDto.inToken,
                outTokens: recordListDto.outToken
            })).valueOf()
            await entityManager.save(UserListEntity, user)
        });
    }

    /**
     * 获取用户某个时间段内，某个模型(未指定获取所有模型)的使用记录
     */
    async getUserRecordListByCondition(userId: string, startDate: string, endDate: string, model: string): Promise<RecordListEntity[]> {
        const qb = this.recordRepository.createQueryBuilder('record');
        qb.where({userId})
        qb.leftJoinAndMapOne('record.userInfo', UserListEntity, 'user', 'record.userId = user.userId')
        if (startDate) {
            qb.andWhere('record.date >= :startDate', { startDate });
        }
        if (endDate) {
            qb.andWhere('record.date <= :endDate', { endDate });
        }
        if (model) {
            qb.andWhere({model})
        }
        qb.orderBy({
            'record.date': 'DESC'
        })
        return qb.getMany();
    }
}
